﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.Data.SQLite;
using System.Data;
using System.Threading;

namespace GetDistanceByBing
{
    class Program
    {
        private static readonly string CONN_STR = "Data Source=postal.db3;Pooling=true;FailIfMissing=false";
        private static readonly string MSKEY = "AmkmkJT2yJ76DduvvNYjAZ6xq2qZTic9qOL6K2HeC3fAMUtlaeLHsewYaXjI3yR8";
        private static readonly string BING_URL = "http://dev.virtualearth.net/REST/V1/Routes?output=xml&wp.0={0},{1}&wp.1={2},{3}&key={4}";
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("get [FromPostal] [ToPostal] or get [ToPostal]");
                return;
            }

            //SAN FRANCISCO 圣弗朗西斯科（旧金山） 37.8/-122.416667   94111
            //LONG BEACH/长滩  37.8/-118.216667   90801
            //LOS ANGELES/洛杉矶  33.716667/-118.26667   90731
            //string[] frmList = { "37.8/-122.416667", "37.8/-118.216667", "33.716667/-118.26667" };
            List<System.String> frmList = new List<System.String>();
            string toPostal = string.Empty;
            if (args.Length == 2)
            {
                frmList.Add(args[0].ToString());
                toPostal = args[1].ToString();
            }
            else
            {
                toPostal = args[0].ToString();
                frmList.Add("90731");
                frmList.Add("90801");
                frmList.Add("94111");
            }

            double dis = 0;
            //计算经纬度
            double frmLatitude = 0, frmLongitude = 0, toLatitude = 0, toLongitude = 0;
            string bing_xml = string.Empty;
            try
            {
                for (int i = 0; i < frmList.Count;i++ )
                {
                    ConvertGPS(GetGPSbyPostal(frmList[i]), ref frmLatitude, ref frmLongitude);
                    ConvertGPS(GetGPSbyPostal(toPostal), ref toLatitude, ref toLongitude);
                    //计算距离            
                    GetDistance(frmLatitude, frmLongitude, toLatitude, toLongitude, ref dis, ref bing_xml);
                    SaveData(frmList[i], toPostal, bing_xml, dis);
                    Console.WriteLine("{0} - {1} : {2},sleep {3} s", frmList[i], toPostal, dis, 5 - i);
                    Thread.Sleep(1000*(5-i));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }            
        }

        private static void SaveData(string frmPostal, string toPostal,string bing_xml,double dis)
        {
            using (SQLiteConnection conn = new SQLiteConnection(CONN_STR))
            {
                conn.Open();
                SQLiteCommand cmd = new SQLiteCommand(conn);
                cmd.CommandText = "INSERT INTO postal_distance(FRM_POSTAL, TO_POSTAL, BING_XML, DISTANCE) VALUES (@FRM_POSTAL, @TO_POSTAL, @BING_XML, @DISTANCE)";

                cmd.Parameters.Clear();
                cmd.Parameters.AddRange(new[] {//添加参数  
                        new SQLiteParameter("@FRM_POSTAL", frmPostal),
                        new SQLiteParameter("@TO_POSTAL", toPostal),
                        new SQLiteParameter("@BING_XML", bing_xml),
                        new SQLiteParameter("@DISTANCE", dis)
                    });
                cmd.ExecuteNonQuery();
            }

        }

        private static void ConvertGPS(string strGPS, ref double frmLatitude, ref double frmLongitude)
        {
            try
            {
                frmLatitude = Convert.ToDouble(strGPS.Substring(0, strGPS.IndexOf("/")));
                frmLongitude = Convert.ToDouble(strGPS.Substring(strGPS.IndexOf("/") + 1));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static string GetGPSbyPostal(string strPostal)
        {
            string gps = "";
            using (SQLiteConnection conn = new SQLiteConnection(CONN_STR))
            {
                conn.Open();
                using (SQLiteCommand command = new SQLiteCommand("select gps from postal where zip_code = '" + strPostal + "'", conn))
                {
                    SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                    DataTable data = new DataTable();
                    adapter.Fill(data);
                    gps = data.Rows[0][0].ToString();
                }
                return gps;
            }
        }
        /// <summary>
        /// 获得字符串中开始和结束字符串中间得值
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="s">开始</param>
        /// <param name="e">结束</param>
        /// <returns></returns> 
        private static string GetRegexValue(string str, string s, string e)
        {
            Regex rg = new Regex("(?<=(" + s + "))[.\\s\\S]*?(?=(" + e + "))", RegexOptions.Multiline | RegexOptions.Singleline);
            return rg.Match(str).Value;
        }

        private static void GetDistance(double frmLatitude, double frmLongitude, double toLatitude, double toLongitude, ref double distance,ref string bing_xml)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(BING_URL, frmLatitude, frmLongitude, toLatitude, toLongitude, MSKEY));
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            bing_xml = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            //Console.WriteLine(retString);


            string strDis = GetRegexValue(bing_xml, "<TravelDistance>", "</TravelDistance>");
            string strDur = GetRegexValue(bing_xml, "<TravelDuration>", "</TravelDuration>");

            if (strDis != "") {
                distance = Convert.ToDouble(strDis);
            }
            
        }


    }
}
